/**
 * Copyright (c) 2016-2023, Michael Yang 杨福海 (fuhai999@gmail.com).
 * <p>
 * Licensed under the GNU Lesser General Public License (LGPL) ,Version 3.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.gnu.org/licenses/lgpl-3.0.txt
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.jpress.pro.filesync;

import com.jfinal.aop.Before;
import com.jfinal.kit.LogKit;
import com.jfinal.kit.Ret;
import com.jfinal.upload.UploadFile;
import io.jboot.Jboot;
import io.jboot.utils.StrUtil;
import io.jboot.web.controller.JbootController;
import io.jboot.web.controller.annotation.RequestMapping;
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author michael yang (fuhai999@gmail.com)
 * @Date: 2020/3/17
 */
@RequestMapping("${jpress.filesync.httpActionPath:/filesync}")
@Before(FileSyncValidator.class)
public class FileSyncController extends JbootController {


    /**
     * 创建新文件
     */
    public void create() {
        UploadFile uploadFile = getFile();
        if (uploadFile == null) {
            renderError(404);
            return;
        }

        File localFile = FileSyncValidator.getCurrentFile();
        Long uploadFileLastModified = getLong("lastModified", 0L);

        //本地文件是新文件，传入进来的是旧文件
        if (localFile.exists() && localFile.lastModified() >= uploadFileLastModified) {
            renderJson(Ret.fail("Newest File exists."));
            return;
        }

        // 可以写入
        else {
            ReentrantLock lock = new ReentrantLock();
            try {
                if (Jboot.isDevMode()) {
                    System.err.println("Received fileCreate:" + StrUtil.urlDecode(getPara("fileName")));
                }

                lock.lock();
                SyncFilesWatcher.me().addIgnoreFile(localFile, lock);


                if (localFile.exists() && !localFile.delete()) {
                    LogKit.error("file can not delete! {}", localFile);
                }

                FileUtils.moveFile(uploadFile.getFile(), localFile);

                if (localFile.exists() && !localFile.setLastModified(uploadFileLastModified)) {
                    LogKit.error("file can not setLastModified! {}", localFile);
                }

                RemoteFilesRecord.recordCreatedFile(localFile);

            } catch (IOException e) {
                LogKit.error(e.toString(), e);
            } finally {
                lock.unlock();
            }

            renderJson(Ret.ok());
        }
    }


    /**
     * 修改文件
     */
    public void change() {
        UploadFile uploadFile = getFile();
        if (uploadFile == null) {
            renderError(404);
            return;
        }

        Long uploadFileLastModified = getLong("lastModified", 0L);

        File localFile = FileSyncValidator.getCurrentFile();
        //本地文件是新文件，传入进来的是旧文件
        if (localFile.exists() && localFile.lastModified() >= uploadFileLastModified) {
            renderJson(Ret.fail("Newest File exists."));
        } else {

            ReentrantLock lock = new ReentrantLock();
            try {
                if (Jboot.isDevMode()) {
                    System.err.println("Received fileChange:" + StrUtil.urlDecode(getPara("fileName")));
                }

                if (localFile.exists() && !localFile.delete()) {
                    LogKit.error("file can not delete! {}", localFile);
                }

                lock.lock();
                SyncFilesWatcher.me().addIgnoreFile(localFile, lock);
                FileUtils.moveFile(uploadFile.getFile(), localFile);

                if (localFile.exists() && !localFile.setLastModified(uploadFileLastModified)) {
                    LogKit.error("file can not setLastModified! {} ", localFile);
                }

                RemoteFilesRecord.recordChangedFile(localFile);

            } catch (IOException e) {
                LogKit.error(e.toString(), e);
            } finally {
                lock.unlock();
            }

            renderJson(Ret.ok());
        }
    }


    /**
     * 删除文件
     */
    public void delete() {
        File localFile = FileSyncValidator.getCurrentFile();

        if (localFile.exists()) {

            ReentrantLock lock = new ReentrantLock();

            if (Jboot.isDevMode()) {
                System.err.println("Received fileDelete:" + StrUtil.urlDecode(getPara("fileName")));
            }

            try {
                lock.lock();
                SyncFilesWatcher.me().addIgnoreFile(localFile, lock);
                if (localFile.delete()) {
                    tryToDeleteParentIfEmpty(localFile);
                }

                RemoteFilesRecord.recordDeleteFile(localFile);
            } finally {
                lock.unlock();
            }

        }

        renderJson(Ret.ok());
    }

    private void tryToDeleteParentIfEmpty(File file) {
        String[] ps = file.getParentFile().list();
        if (ps == null || ps.length == 0) {
            if (!file.getParentFile().delete()) {
                LogKit.error("file can not delete: {}", file.getParentFile());
            }
            tryToDeleteParentIfEmpty(file.getParentFile());
        }
    }

}
